package cn.net.greenet.device.send.policy;

import cn.net.greenet.common.policy_service.PolicySupport;
import cn.net.greenet.db.HibernateUtil;
import cn.net.greenet.db.bean.Currentmessagesequenceno;
import cn.net.greenet.db.bean.CurrentmessagesequencenoId;
import cn.net.greenet.db.bean.Dpiendpointbean;
import cn.net.greenet.db.bean.Messageoutgoingsendingqueue;
import cn.net.greenet.db.bean.Policyrepositoryinstance;
import cn.net.greenet.send.policy.SendPolicyUntil;
import com.ambimmort.prserver.bean.RepositoryOperationBean;
import com.ambimmort.umessage.UcType;
import com.ambimmort.umessage.exceptions.UcTypeException;
import com.ambimmort.umessage.uc.outgoing.uvm.x82;
import com.ambimmort.umessage.uc.outgoing.uvm.x85;
import com.ambimmort.umessage.uc.outgoing.uvm.xC3;
import com.ambimmort.umessage.uc.outgoing.uvm.xC4;
import com.ambimmort.umessage.uc.outgoing.uvm.xCB;
import com.ambimmort.umessage.uc.outgoing.uvm.xCC;
import com.ambimmort.umessage.uc.outgoing.uvm.xCF;
import com.ambimmort.umessage.uc.outgoing.vm.x00;
import com.ambimmort.umessage.uc.outgoing.vm.x01;
import com.ambimmort.umessage.uc.outgoing.vm.x02;
import com.ambimmort.umessage.uc.outgoing.vm.x05;
import com.ambimmort.umessage.uc.outgoing.vm.x06;
import com.ambimmort.umessage.uc.outgoing.vm.x07;
import com.ambimmort.umessage.uc.outgoing.vm.x08;
import com.ambimmort.umessage.uc.outgoing.vm.x09;
import com.ambimmort.umessage.uc.outgoing.vm.x0A;
import com.ambimmort.umessage.uc.outgoing.vm.x40;
import com.ambimmort.umessage.uc.outgoing.vm.x41;
import com.ambimmort.umessage.uc.outgoing.vm.x42;
import com.ambimmort.umessage.uc.outgoing.vm.x43;
import com.ambimmort.umessage.uc.outgoing.vm.x45;
import com.ambimmort.umessage.uc.outgoing.vm.xC7;
import com.ambimmort.umessage.uc.outgoing.vm.xC8;
import com.ambimmort.umessage.uc.outgoing.vm.xC9;
import com.ambimmort.umessage.uc.outgoing.vm.xCA;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

/**
 * 响应DPI的策略同步请求，回应DPI策略变化
 *
 * @author liangdelin
 */
public class AddSendPolicyUntil {

    public static int[] arr = new int[]{3, 2, 1};  //操作的数组

    public static boolean send(int dpi_id, List<Map<String, String>> data) {
        Map<String, String> temportData = null;
        int messageNo = 0;
        String policy = "";  //策略的JSON内容
        String messageType = ""; //MessageType
        long messageSequenceNo = 0;
        long messageSerialNo = 0;
        int policyRepositoryID = 0;
        int operation = 0;  //策略操作标示
        byte[] message = null;
        ByteArrayOutputStream os = null;
        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session session = sf.openSession();
        session.clear();
        Transaction tx = session.beginTransaction();
        List<RepositoryOperationBean> temporyPolicyOperation = null;
        Messageoutgoingsendingqueue queue = null;
        Dpiendpointbean bean = null;
        try {
            for (int i = 0; i < data.size(); i++) {
                int messageNoSet = 0;
                int messageSequenceNoSet = 0;
                temportData = data.get(i);
                messageType = temportData.get("message_type");
                temporyPolicyOperation = PolicySupport.getInstance().getApi().getUpdatingOperationBeans(messageType, temportData.get("instance"), Long.parseLong(temportData.get("dpi_edition")));
                queue = new Messageoutgoingsendingqueue();
                messageNoSet = Math.abs(new Random(System.currentTimeMillis()).nextInt()) % 100000;
                messageSequenceNoSet = Math.abs(new Random(System.currentTimeMillis()).nextInt()) % 100000;
                xC3 msg = new xC3();
                //SetMessageNo
                //SetMessageSequenceNo
                msg.setMessageType(UcType.newUINT1(Integer.parseInt(messageType.substring(2), 16)));  //0xC3
                msg.setMessageSerialNo(UcType.newUINT4(getInstanceVersion(messageType, data.get(i).get("instance"))));
                for (int j = 0; j < temporyPolicyOperation.size(); j++) {
                    messageNo = temporyPolicyOperation.get(j).getMessageNo();
                    operation = temporyPolicyOperation.get(j).getOperation();
                    policy = temporyPolicyOperation.get(j).getContent();
                    policyRepositoryID = AddSendPolicyUntil.getInstanceId(data.get(i).get("instance"));
                    messageSequenceNo = AddSendPolicyUntil.getDBMessageSequenceNo(dpi_id + "", policyRepositoryID + "");
                    messageSerialNo = SendPolicyUntil.getMessageSerialNo(messageType, data.get(i).get("instance"), messageNo, dpi_id + "", policyRepositoryID + "");
                    message = getMessage(policy, data.get(i).get("message_type"), messageNo, messageSerialNo, messageSequenceNo); //二进制 UC Message

                    xC3.MessageChange mch = new xC3.MessageChange();
                    mch.setChanggedMessageNo(UcType.newUINT4(messageNo));
                    mch.setMessageChangeType(UcType.newUINT1(arr[operation]));
                    int len = message.length;
                    byte[] a = UcType.newUINT4(len).getBytes();
                    os = new ByteArrayOutputStream();
                    os.write(a);
                    os.write(message);
                    mch.setMessageContents(new UcType.UObject(os.toByteArray()));
                    msg.getMessages().add(mch);
                    os.close();
                }
                if (msg.toBytes().length > 25) {
                    queue.setMessageType("0xC3");  //DPI策略同步请求
                    queue.setMessageNo(messageNoSet); //随机产生的MessageNo
                    queue.setMessageSequenceNo(messageSequenceNoSet);  //随机产生MessageSequenceNo
                    queue.setType(1); // 0:程序自动  1:手动
                    queue.setCreateTime(new Date());
                    queue.setPacket(msg.toBytes());  //二进制内容
                    bean = new Dpiendpointbean();
                    bean.setId(dpi_id);
                    queue.setDpiendpointbean(bean);
                    session.save(queue);
                }
            }
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
            return false;
        } finally {
            session.close();
        }
        return true;
    }

    /**
     * 获取某个仓库最新的版本号
     *
     * @param type
     * @param instance
     * @return
     */
    public static long getInstanceVersion(String type, String instance) {

        return PolicySupport.getInstance().getApi().getHeadVersion(type, instance);
    }

    public static byte[] getMessage(String policy, String type, int messageNo, long SerialNo, long sequenceNo) throws UcTypeException, Exception {
        if ("0x45".equals(type)) {
            x45 msg0x45 = new x45();
            msg0x45.parseJSON(policy);
            msg0x45.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x45.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x45.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x45.toBytes();
        } else if ("0x00".equals(type)) {
            x00 msg0x00 = new x00();
            msg0x00.parseJSON(policy);
            msg0x00.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x00.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x00.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x00.toBytes();
        } else if ("0x01".equals(type)) {
            x01 msg0x01 = new x01();
            msg0x01.parseJSON(policy);
            msg0x01.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x01.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x01.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x01.toBytes();
        } else if ("0x40".equals(type)) {
            x40 msg0x40 = new x40();
            msg0x40.parseJSON(policy);
            msg0x40.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x40.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x40.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x40.toBytes();
        } else if ("0x43".equals(type)) {
            x43 msg0x43 = new x43();
            msg0x43.parseJSON(policy);
            msg0x43.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x43.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x43.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x43.toBytes();
        } else if ("0x85".equals(type)) {
            x85 msg0x85 = new x85();
            msg0x85.parseJSON(policy);
            msg0x85.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x85.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
//            msg0x85.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x85.toBytes();
        } else if ("0xC7".equals(type)) {
            xC7 msg0xC7 = new xC7();
            msg0xC7.parseJSON(policy);
            msg0xC7.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xC7.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0xC7.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0xC7.toBytes();
        } else if ("0xC8".equals(type)) {
            xC8 msg0xC8 = new xC8();
            msg0xC8.parseJSON(policy);
            msg0xC8.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xC8.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0xC8.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0xC8.toBytes();
        } else if ("0xC9".equals(type)) {
            xC9 msg0xC9 = new xC9();
            msg0xC9.parseJSON(policy);
            msg0xC9.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xC9.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0xC9.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0xC9.toBytes();
        } else if ("0xCA".equals(type)) {
            xCA msg0xCA = new xCA();
            msg0xCA.parseJSON(policy);
            msg0xCA.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xCA.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0xCA.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0xCA.toBytes();
        } else if ("0x09".equals(type)) {
            x09 msg0x09 = new x09();
            msg0x09.parseJSON(policy);
            msg0x09.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x09.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x09.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x09.toBytes();
        } else if ("0x02".equals(type)) {
            x02 msg0x02 = new x02();
            msg0x02.parseJSON(policy);
            msg0x02.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x02.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x02.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x02.toBytes();
        } else if ("0x05".equals(type)) {
            x05 msg0x05 = new x05();
            msg0x05.parseJSON(policy);
            msg0x05.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x05.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x05.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x05.toBytes();
        } else if ("0x42".equals(type)) {
            x42 msg0x42 = new x42();
            msg0x42.parseJSON(policy);
            msg0x42.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x42.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x42.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x42.toBytes();
        } else if ("0x82".equals(type)) {
            x82 msg0x82 = new x82();
            msg0x82.parseJSON(policy);
            msg0x82.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x82.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
//            msg0x82.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x82.toBytes();
        } else if ("0x08".equals(type)) {
            x08 msg0x08 = new x08();
            msg0x08.parseJSON(policy);
            msg0x08.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x08.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x08.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x08.toBytes();
        } else if ("0x0A".equals(type)) {
            x0A msg0x0A = new x0A();
            msg0x0A.parseJSON(policy);
            msg0x0A.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x0A.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x0A.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x0A.toBytes();
        } else if ("0x41".equals(type)) {
            x41 msg0x41 = new x41();
            msg0x41.parseJSON(policy);
            msg0x41.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x41.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x41.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x41.toBytes();
        } else if ("0xCF".equals(type)) {
            xCF msg0xCF = new xCF();
            msg0xCF.parseJSON(policy);
            msg0xCF.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xCF.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
//            msg0xCF.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0xCF.toBytes();
        } else if ("0x06".equals(type)) {
            x06 msg0x06 = new x06();
            msg0x06.parseJSON(policy);
            msg0x06.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x06.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x06.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x06.toBytes();
        } else if ("0x07".equals(type)) {
            x07 msg0x07 = new x07();
            msg0x07.parseJSON(policy);
            msg0x07.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0x07.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            msg0x07.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0x07.toBytes();
        } else if ("0xC4".equals(type)) {
            xC4 msg0xC4 = new xC4();
            msg0xC4.parseJSON(policy);
            msg0xC4.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xC4.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
//            msg0xC4.setMessageSerialNo(UcType.newUINT4(SerialNo));
            return msg0xC4.toBytes();
        } else if ("0xCB".equals(type)) {
            xCB msg0xCB = new xCB();
            msg0xCB.parseJSON(policy);
            msg0xCB.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xCB.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            return msg0xCB.toBytes();
        } else if ("0xCC".equals(type)) {
            xCC msg0xCC = new xCC();
            msg0xCC.parseJSON(policy);
            msg0xCC.getHeader().setMessageNo(UcType.newUINT4(messageNo));
            msg0xCC.getHeader().setMessageSequenceNo(UcType.newUINT4(sequenceNo));
            return msg0xCC.toBytes();
        }

        return null;
    }

    /**
     * 获取策略库实例的ID
     *
     * @param instanceName
     * @return
     */
    public static int getInstanceId(String instanceName) {
        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session session = sf.openSession();
        session.clear();
        Policyrepositoryinstance policyBean = null;
        Query query = session.createQuery("SELECT instance FROM Policyrepositoryinstance AS instance WHERE instance.instanceName=:name");
        query.setParameter("name", instanceName);
        List l = query.list();
        policyBean = (Policyrepositoryinstance) l.get(0);
        session.close();
        return policyBean.getId();
    }

    /**
     * 获取策略指定策略的版本号 optional 并更新DB中version 版本号
     *
     * @param type
     * @param instance
     * @param messageNo
     * @return
     */
    public static long getMessageSerialNo(String type, String instance, int messageNo) {
        long version = 0;
        if ("0xCF".equals(type)) {
            return 0;
        } else if ("0x85".equals(type)) {
            return 0;
        } else if ("0x82".equals(type)) {
            return 0;
        } else if ("0xC4".equals(type)) {
            return 0;
        } else if ("0xCC".equals(type)) {
            return 0;
        } else if ("0xCB".equals(type)) {
            return 0;
        } else {
            version = PolicySupport.getInstance().getApi().getMessage(type, instance, messageNo).getId();
        }
        return version;
    }

    /**
     * 获取MessageSequenceNo
     *
     * @param dpiID
     * @param policyRepositoryID
     * @return
     */
    public static long getDBMessageSequenceNo(String dpiID, String policyRepositoryID) {
        CurrentmessagesequencenoId aa = new CurrentmessagesequencenoId(Integer.parseInt(dpiID), Integer.parseInt(policyRepositoryID));
        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session session = sf.openSession();
        session.clear();
        Currentmessagesequenceno sequenceNo = (Currentmessagesequenceno) session.get(Currentmessagesequenceno.class, aa);
        Transaction tx = session.beginTransaction();
        long seqNo = 0;
        try {
            if (sequenceNo == null) {
                sequenceNo = new Currentmessagesequenceno();
                sequenceNo.setId(aa);
                sequenceNo.setMessageSequenceNo(0);
                session.save(sequenceNo);
                seqNo = 0;
            } else {
                seqNo = sequenceNo.getMessageSequenceNo();
                sequenceNo.setMessageSequenceNo(seqNo);
                session.update(sequenceNo);
            }
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
            return seqNo;
        }
    }

}
